home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / api / amiga_syscalls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  11.2 KB  |  549 lines

  1. RCS_ID_C="$Id: amiga_syscalls.c,v 3.5 1994/03/22 08:41:36 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  * 
  7.  * Created: Sun Feb 14 18:35:48 1993 too
  8.  * Last modified: Wed Feb 16 01:18:32 1994 jraja
  9.  * 
  10.  * HISTORY
  11.  * $Log: amiga_syscalls.c,v $
  12.  * Revision 3.5  1994/03/22  08:41:36  jraja
  13.  * Added calls to the libPtr->fdCallback to the appropriate places.
  14.  *
  15.  * Revision 3.4  1994/02/15  23:18:42  jraja
  16.  * Changed sdFind() to return the sd via LONG * instead of ULONG * to be
  17.  * consistent with API types.
  18.  *
  19.  * Revision 3.3  1994/01/07  15:40:29  too
  20.  * Bug fixes after revision 3.1. Now tested.
  21.  *
  22.  * Revision 3.2  1994/01/06  13:39:11  too
  23.  * Moved send and recv functions to amiga_sendrecv.c
  24.  *
  25.  * Revision 3.1  1994/01/04  14:32:29  too
  26.  * Added function sdFind(). Revised socket() and accept() to use sdFind()
  27.  * and socket usage bitmask.
  28.  *
  29.  * Revision 1.25  1993/06/04  11:16:15  jraja
  30.  * Fixes for first public release.
  31.  *
  32.  */
  33.  
  34. #include <conf.h>
  35.  
  36. #include <sys/param.h>
  37. #include <sys/systm.h>
  38. #include <sys/malloc.h>
  39. #include <sys/mbuf.h>
  40. #include <sys/protosw.h>
  41. #include <sys/socket.h>
  42. #include <sys/socketvar.h>
  43. #include <sys/synch.h>
  44. #include <sys/errno.h>
  45.  
  46. #include <exec/types.h>
  47. #include <exec/libraries.h>
  48. #include <exec/semaphores.h>
  49.  
  50. #include <api/amiga_api.h>
  51. #include <api/amiga_libcallentry.h>
  52. #include <sockargs.h>
  53.  
  54. #include <amitcp/socketbasetags.h>
  55.  
  56. #include <kern/uipc_socket_protos.h>
  57. #include <kern/uipc_socket2_protos.h>
  58.   
  59.  
  60. LONG SAVEDS RAF4(_socket,
  61.          struct SocketBase *,     libPtr,        a6,
  62.          LONG,            domain,        d0,
  63.          LONG,            type,        d1,
  64.          LONG,            protocol,    d2)
  65.  
  66. #if 0
  67. {
  68. #endif
  69.   
  70.   struct socket *so;
  71.   LONG fd, error;
  72.  
  73.   CHECK_TASK();
  74.  
  75.   if (error = sdFind(libPtr, &fd))
  76.       goto Return;
  77.   
  78.   ObtainSyscallSemaphore(libPtr);
  79.   error = socreate(domain, &so, type, protocol);
  80.   ReleaseSyscallSemaphore(libPtr);
  81.  
  82.   if (! error) {
  83.     /*
  84.      * Tell the link library about the new fd
  85.      */
  86.     if (libPtr->fdCallback)
  87.       error = libPtr->fdCallback(fd, FDCB_ALLOC);
  88.     if (! error) {
  89.       so->so_refcnt = 1;        /* reference count is pure AmiTCP addition */
  90.       libPtr->dTable[fd] = so;
  91.       FD_SET(fd, (fd_set *)(libPtr->dTable + libPtr->dTableSize));
  92.     }
  93.   }
  94.   
  95.  Return: API_STD_RETURN(error, fd);
  96. }
  97.  
  98.  
  99. LONG SAVEDS RAF4(_bind,
  100.          struct SocketBase *,    libPtr,        a6,
  101.          LONG,            s,        d0,
  102.          caddr_t,        name,        a0,
  103.          LONG,            namelen,    d1)
  104. #if 0
  105. {
  106. #endif  
  107.  
  108.   struct socket *so;
  109.   struct mbuf *nam;
  110.   LONG error;
  111.  
  112.   CHECK_TASK();
  113.   ObtainSyscallSemaphore(libPtr);
  114.   
  115.   if (error = getSock(libPtr, s, &so))
  116.     goto Return;
  117.   if (error = sockArgs(&nam, name, namelen, MT_SONAME))
  118.     goto Return;
  119.   error = sobind(so, nam);
  120.   m_freem(nam);
  121.  
  122.  Return:
  123.   ReleaseSyscallSemaphore(libPtr);
  124.   API_STD_RETURN(error, 0);
  125. }
  126.  
  127. LONG SAVEDS RAF3(_listen,
  128.          struct SocketBase *,    libPtr,        a6,
  129.          LONG,            s,        d0,
  130.          LONG,            backlog,    d1)
  131. #if 0
  132. {
  133. #endif
  134.  
  135.   struct socket *so;
  136.   LONG error;
  137.   
  138.   CHECK_TASK();
  139.   ObtainSyscallSemaphore(libPtr);
  140.   
  141.   if (error = getSock(libPtr, s, &so))
  142.     goto Return;
  143.   error = solisten(so, backlog);
  144.  
  145.  Return:
  146.   ReleaseSyscallSemaphore(libPtr);
  147.   API_STD_RETURN(error, 0);
  148.  
  149. }
  150.     
  151. LONG SAVEDS RAF4(_accept,
  152.          struct SocketBase *,    libPtr,        a6,
  153.          LONG,            s,        d0,
  154.          caddr_t,        name,        a0,
  155.          ULONG *,        anamelen,    a1)
  156. #if 0
  157. {
  158. #endif
  159.  
  160.   struct socket *so;
  161.   struct mbuf *nam;
  162.   spl_t old_spl;
  163.   LONG error, fd;
  164.  
  165.   CHECK_TASK();
  166.   ObtainSyscallSemaphore(libPtr);
  167.  
  168.   if (error = getSock(libPtr, s, &so))
  169.     goto Return;
  170.  
  171.   old_spl = splnet();
  172.   if ((so->so_options & SO_ACCEPTCONN) == 0) {
  173.     error = EINVAL;
  174.     goto Return_spl;
  175.   }
  176.   if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
  177.     error = EWOULDBLOCK;
  178.     goto Return_spl;
  179.   }
  180.   while (so->so_qlen == 0 && so->so_error == 0) {
  181.     if (so->so_state & SS_CANTRCVMORE) {
  182.       so->so_error = ECONNABORTED;
  183.       break;
  184.     }
  185.     if (error = tsleep(libPtr, (caddr_t)&so->so_timeo, netcon, NULL)) {
  186.       goto Return_spl;
  187.     }
  188.   }
  189.   if (so->so_error) {
  190.     error = so->so_error;
  191.     so->so_error = 0;
  192.     goto Return_spl;
  193.   }
  194.    
  195.   if (error = sdFind(libPtr, &fd)) {
  196.     goto Return_spl;
  197.   }
  198.  
  199.   /*
  200.    * Tell the link library about the new fd
  201.    */
  202.   if (libPtr->fdCallback)
  203.     if (error = libPtr->fdCallback(fd, FDCB_ALLOC))
  204.       goto Return_spl;
  205.  
  206.   {
  207.     struct socket *aso = so->so_q;
  208.     if (soqremque(aso, 1) == 0)
  209.       panic("accept");
  210.     so = aso;
  211.   }    
  212.  
  213.   libPtr->dTable[fd] = so;
  214.   FD_SET(fd, (fd_set *)(libPtr->dTable + libPtr->dTableSize));
  215.   so->so_refcnt = 1;  /* pure AmiTCP addition */
  216.  
  217.   nam = m_get(M_WAIT, MT_SONAME);
  218.   (void)soaccept(so, nam);  /* is this always successful */
  219.   if (name) {
  220.     if (*anamelen > nam->m_len)
  221.       *anamelen = nam->m_len;
  222.     /* SHOULD COPY OUT A CHAIN HERE */
  223.     aligned_bcopy(mtod(nam, caddr_t), (caddr_t)name, (u_int)*anamelen);
  224.   }
  225.   m_freem(nam);
  226.  
  227.  Return_spl:
  228.   splx(old_spl);
  229.  
  230.  Return:
  231.   ReleaseSyscallSemaphore(libPtr);
  232.   API_STD_RETURN(error, fd);
  233. }
  234.  
  235. LONG SAVEDS RAF4(_connect,
  236.          struct SocketBase *,    libPtr,        a6,
  237.          LONG,            s,        d0,
  238.          caddr_t,        name,        a0,
  239.          LONG,            namelen,    d1)
  240. #if 0
  241. {
  242. #endif
  243.  
  244.   /*register*/ struct socket *so;
  245.   struct mbuf *nam;
  246.   LONG error;
  247.   spl_t old_spl;
  248.  
  249.   CHECK_TASK();
  250.   ObtainSyscallSemaphore(libPtr);
  251.  
  252.   if (error = getSock(libPtr, s, &so))
  253.     goto Return;
  254.   if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
  255.     error = EALREADY;
  256.     goto Return;
  257.   }
  258.   if (error = sockArgs(&nam, name, namelen, MT_SONAME))
  259.     goto Return;
  260.   error = soconnect(so, nam);
  261.   if (error)
  262.     goto bad;
  263.   if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
  264.     m_freem(nam);
  265.     error = EINPROGRESS;
  266.     goto Return;
  267.   }    
  268.   old_spl = splnet();
  269.   while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
  270.     if (error = tsleep(libPtr,(caddr_t)&so->so_timeo, netcon, NULL))
  271.       break;
  272.   if (error == 0) {
  273.     error = so->so_error;
  274.     so->so_error = 0;
  275.   }
  276.   splx(old_spl);
  277.  bad:
  278.   so->so_state &= ~SS_ISCONNECTING;
  279.   m_freem(nam);
  280.   if (error == ERESTART)
  281.     error = EINTR;
  282.  
  283.  Return:
  284.   ReleaseSyscallSemaphore(libPtr);
  285.   API_STD_RETURN(error, 0);
  286.  
  287. }
  288.  
  289. LONG SAVEDS RAF3(_shutdown,
  290.          struct SocketBase *,    libPtr,    a6,
  291.          LONG,            s,    d0,
  292.          LONG,            how,    d1)
  293. #if 0
  294. {
  295. #endif
  296.  
  297.   struct socket *so;
  298.   LONG error;
  299.  
  300.   CHECK_TASK();
  301.   ObtainSyscallSemaphore(libPtr);
  302.  
  303.   if (error = getSock(libPtr, s, &so))
  304.     goto Return;
  305.  
  306.   error = soshutdown(so, how);
  307.  
  308.  Return:
  309.   ReleaseSyscallSemaphore(libPtr);
  310.   API_STD_RETURN(error, 0);
  311. }
  312.  
  313. LONG SAVEDS RAF6(_setsockopt,
  314.          struct SocketBase *,    libPtr,        a6,
  315.          LONG,            s,        d0,
  316.          LONG,            level,        d1,
  317.          LONG,            name,        d2,
  318.          caddr_t,        val,        a0,
  319.          ULONG,            valsize,    d3)
  320. #if 0
  321. {
  322. #endif
  323.  
  324.   struct socket *so;
  325.   struct mbuf *m = NULL;
  326.   LONG error;
  327.  
  328.   CHECK_TASK();
  329.   ObtainSyscallSemaphore(libPtr);
  330.  
  331.   if (error = getSock(libPtr, s, &so))
  332.     goto Return;
  333.   if (valsize > MLEN) { /* unsigned catches negative values */
  334.     error = EINVAL;
  335.     goto Return;
  336.   }
  337.   if (val) {
  338.     m = m_get(M_WAIT, MT_SOOPTS);
  339.     if (m == NULL) {
  340.       error = ENOBUFS;
  341.       goto Return;
  342.     }
  343.     bcopy(val, mtod(m, caddr_t), valsize); /* aligned ? */
  344.     m->m_len = (int)valsize;
  345.   }
  346.   error = sosetopt(so, level, name, m);
  347.  
  348.  Return:
  349.   ReleaseSyscallSemaphore(libPtr);
  350.   API_STD_RETURN(error, 0);
  351. }
  352.  
  353.  
  354. LONG SAVEDS RAF6(_getsockopt,
  355.          struct SocketBase *,    libPtr,        a6,
  356.          LONG,            s,        d0,
  357.          LONG,            level,        d1,
  358.          LONG,            name,        d2,
  359.          caddr_t,        val,        a0,
  360.          ULONG *,        avalsize,    a1)
  361. #if 0
  362. {
  363. #endif
  364.  
  365.   struct socket *so;
  366.   struct mbuf *m = NULL;
  367.   ULONG valsize, error;
  368.  
  369.   CHECK_TASK();
  370.   ObtainSyscallSemaphore(libPtr);
  371.  
  372.   if (error = getSock(libPtr, s, &so))
  373.     goto Return;
  374.   
  375.   if (val)
  376.     valsize = *avalsize;
  377.   else
  378.     valsize = 0;
  379.   
  380.   if ((error = sogetopt(so, level, name, &m)) == 0
  381.       && val && valsize && m != NULL) {
  382.     if (valsize > m->m_len)  /* valsize is ULONG */
  383.       valsize = m->m_len;
  384.     bcopy(mtod(m, caddr_t), val, (u_int)valsize); /* aligned ? */
  385.     *avalsize = valsize;
  386.   }
  387.   if (m != NULL)
  388.     (void) m_free(m);
  389.  
  390.  Return:
  391.   ReleaseSyscallSemaphore(libPtr);
  392.   API_STD_RETURN(error, 0);
  393. }
  394.  
  395. LONG SAVEDS RAF4(_getsockname,
  396.          struct SocketBase *,    libPtr,    a6,
  397.          LONG,            fdes,    d0,
  398.          caddr_t,        asa,    a0,
  399.          ULONG *,        alen,    a1)
  400. #if 0
  401. {
  402. #endif
  403.  
  404.   /*register*/
  405.   struct socket *so;
  406.   struct mbuf *m;
  407.   LONG error;
  408.  
  409.   CHECK_TASK();
  410.   ObtainSyscallSemaphore(libPtr);
  411.  
  412.   if (error = getSock(libPtr, fdes, &so))
  413.     goto Return;
  414.  
  415.   m = m_getclr(M_WAIT, MT_SONAME);    
  416.   if (m == NULL) {
  417.     error = ENOBUFS;
  418.     goto Return;
  419.   }
  420.   if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
  421.     goto bad;
  422.   if (*alen > m->m_len)
  423.     *alen = m->m_len;
  424.   aligned_bcopy(mtod(m, caddr_t), (caddr_t)asa, (u_int)*alen);
  425.  
  426.  bad:
  427.   m_freem(m);
  428.  
  429.  Return:
  430.   ReleaseSyscallSemaphore(libPtr);
  431.   API_STD_RETURN(error, 0);
  432. }
  433.  
  434. LONG SAVEDS RAF4(_getpeername,
  435.          struct SocketBase *,    libPtr,    a6,
  436.          LONG,            fdes,    d0,
  437.          caddr_t,        asa,    a0,
  438.          ULONG *,        alen,    a1)
  439. #if 0
  440. {
  441. #endif
  442.  
  443.   /*register*/
  444.   struct socket *so;
  445.   struct mbuf *m;
  446.   LONG error;
  447.  
  448.   CHECK_TASK();
  449.   ObtainSyscallSemaphore(libPtr);
  450.  
  451.   if (error = getSock(libPtr, fdes, &so))
  452.     goto Return;
  453.  
  454.   if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
  455.     error = ENOTCONN;
  456.     goto Return;
  457.   }
  458.  
  459.   m = m_getclr(M_WAIT, MT_SONAME);
  460.   if (m == NULL) {
  461.     error = ENOBUFS;
  462.     goto Return;
  463.   }
  464.  
  465.   if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
  466.     goto bad;
  467.   if (*alen > m->m_len)
  468.     *alen = m->m_len;
  469.   aligned_bcopy(mtod(m, caddr_t), (caddr_t)asa, (u_int)*alen);
  470.  
  471.  bad:
  472.   m_freem(m);
  473.  
  474.  Return:
  475.   ReleaseSyscallSemaphore(libPtr);
  476.   API_STD_RETURN(error, 0);
  477. }
  478.  
  479. LONG sockArgs(struct mbuf **mp,
  480.              caddr_t buf,    /* aligned */
  481.              LONG buflen,
  482.              LONG type)
  483. {
  484.   register struct mbuf *m;
  485.   LONG error = 0;
  486.  
  487.   if ((u_int)buflen > MLEN)
  488.     return (EINVAL);
  489.  
  490.   m = m_get(M_WAIT, type);
  491.   if (m == NULL)
  492.     return (ENOBUFS);
  493.   m->m_len = buflen;
  494.  
  495.   aligned_bcopy(buf, mtod(m, caddr_t), (u_int)buflen);
  496.   *mp = m;
  497.   if (type == MT_SONAME)
  498.     mtod(m, struct sockaddr *)->sa_len = buflen;
  499.  
  500.   return (error);
  501. }
  502.  
  503. /*
  504.  * sdFind replaces old fdAlloc. This version now looks for free socket
  505.  * from socket usage bitmask stored right after descriptor table
  506.  */
  507.  
  508. LONG sdFind(struct SocketBase * libPtr, LONG *fdp)
  509. {
  510.   int bit, moffset;
  511.   ULONG * smaskp;
  512.   int mlongs = (libPtr->dTableSize - 1) / NFDBITS + 1;
  513.  
  514.   moffset = 0, smaskp = (ULONG  *)(libPtr->dTable + libPtr->dTableSize);
  515.   while (mlongs) {
  516.     unsigned long cmask = *smaskp;
  517.     unsigned long dmask = cmask + 1;
  518.  
  519.     if (dmask == 0) {
  520.       mlongs--, smaskp++, moffset += 32;
  521.       continue;    /* current  mask is full (cmask = 0xFFFFFFFF) */
  522.     }
  523.     cmask = ((cmask ^ dmask) >> 1) + 1; /* now only one bit set ! */
  524.  
  525.     bit = (cmask & 0xFFFF0000)? 16: 0;
  526.     if (cmask & 0xFF00FF00) bit += 8;
  527.     if (cmask & 0xF0F0F0F0) bit += 4;
  528.     if (cmask & 0xCCCCCCCC) bit += 2;
  529.     if (cmask & 0xAAAAAAAA) bit += 1;
  530.  
  531.     /*
  532.      * Check if link library agrees with us on the next free fd...
  533.      */
  534.     if (libPtr->fdCallback)
  535.       if (libPtr->fdCallback(moffset + bit, FDCB_CHECK)) {
  536.     *smaskp |= cmask; /* mark this fd as used */
  537.     continue; /* search for the next _bit_ */
  538.       }
  539.  
  540.     if (moffset + bit >= libPtr->dTableSize)
  541.       break;
  542.     else {
  543.       *fdp = moffset + bit;
  544.       return 0;
  545.     }
  546.   }
  547.   return (EMFILE);
  548. }
  549.